﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;

namespace EIA.BLLTool
{
    public class BllTemplate
    {
        public BllTemplate(string dllpath, string output)
        {
            _assembly = Assembly.LoadFrom(dllpath);
            _output = output;
        }
        string _output = null;
        public Assembly _assembly = null;

        public void Generate(string output_filename_pattern)
        {
            Type[] types = _assembly.GetTypes();
            string dir = System.IO.Path.GetDirectoryName(_assembly.Location);
            foreach (var t in types)
            {
                if (t.IsInterface)
                {
                    GenBlpModule(t);
                    GenProxy(t);
                }
            }
        }

        private void SaveFile(string file, string content)
        {
            if (File.Exists(file))
            {
                File.Delete(file);
            }
            if (!Directory.Exists(Path.GetDirectoryName(file))) Directory.CreateDirectory(Path.GetDirectoryName(file));
            using (FileStream s = File.Open(file, FileMode.Create))
            {
                StreamWriter sw = new StreamWriter(s);
                sw.Write(content);
                sw.Flush();
            }
        }

        private void GenBlpModule(Type t)
        {
            string clsname = "";
            Regex reg = new Regex("(?<=^I)\\w*(?=Blp$)");
            if (reg.IsMatch(t.Name))
            {
                Match match = reg.Match(t.Name);
                clsname = match.Value;
            }
            string temp =
@"using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DotNETX.Business.Module.MefExtension;
using {1};

namespace {1}.BusinessModule
{{
    public class {0}BM : MefBusinesModule
    {{
        public override void Initial()
        {{
            this.BLOInstance = new {0}Blp();
        }}
    }}
}}";
            string content = string.Format(temp, clsname, t.Namespace);
            string file = clsname + "BM.cs";
            SaveFile(Path.Combine(_output, "bm", file), content);

        }
        private void GenProxy(Type t)
        {
            string clsname = "";
            Regex reg = new Regex("(?<=^I)\\w*(?=Blp$)");
            if (reg.IsMatch(t.Name))
            {
                Match match = reg.Match(t.Name);
                clsname = match.Value;
            }
            string nameSpace = t.Namespace;
            string temp =
@"using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ServiceModel;
using EIA.WCFService.ClientProxy;

namespace {1}.ClientProxy
{{
    /// <summary>
    /// generated by binking
    /// </summary>
    public class {0}Proxy : ProxyBase
    {{
        {2}
    }}
}}";
            string method_temp =
@"
        public IClientChannel {1}({3} Action<{2}> callback, Action<Exception> errorCallback = null)
        {{
            object[] args = new object[] {{{4} }};
            string json_args = Newtonsoft.Json.JsonConvert.SerializeObject(args);

            return string.IsNullOrEmpty(X.ServiceAddress) ?
                CallFuncByAddToken2Headder(""{0}"", ""{1}"", json_args, callback, errorCallback) :
                CallFuncByAddToken2Headder(X.ServiceAddress, ""{0}"", ""{1}"", json_args, callback, errorCallback);
        }}"
;

            string methods = "";

            MethodInfo[] mis = t.GetMethods();
            foreach (MethodInfo mi in mis)
            {
                string arg_list = "";
                string json_arg_list = "";
                ParameterInfo[] pis = mi.GetParameters();
                foreach (ParameterInfo pi in pis)
                {
                    arg_list += string.Format("{0} {1},", GetTypeExp(pi.ParameterType), pi.Name);
                    json_arg_list += string.Format(", Newtonsoft.Json.JsonConvert.SerializeObject({0})", pi.Name);
                }
                json_arg_list = json_arg_list.Length > 0 ? json_arg_list.Substring(1) : json_arg_list;
                string mbody = string.Format(method_temp, t.Namespace + "." + clsname + "Blp", mi.Name, GetTypeExp(mi.ReturnType), arg_list, json_arg_list);
                methods += mbody.Replace("<void>", "");
            }

            string content = string.Format(temp, clsname, nameSpace, methods);
            string file = clsname + "Proxy.cs";
            SaveFile(Path.Combine(_output, "proxy", file), content);
        }

        string GetTypeExp(Type t)
        {
            if (t == typeof(void)) return "void";
            if (t.IsGenericType)
            {
                string nameSpace = t.Namespace;
                string name = t.Name.Substring(0, t.Name.IndexOf("`"));
                string n = t.Name;
                Type[] genericArgs = t.GetGenericArguments();
                string[] strGenericArgs = new string[genericArgs.Length];
                for (int i = 0; i < genericArgs.Length; i++)
                {
                    strGenericArgs[i] = GetTypeExp(genericArgs[i]);
                }
                return string.Format("{0}.{1}<{2}>",nameSpace, name, string.Join(", ", strGenericArgs));
            }
            return t.FullName;

        }

    }
}
